﻿using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.Serialization;
using CrawlerCore.XmlData;
using CrawlerCore.XmlDataForeign;
using CrawlerCore.Helper;
using CrawlerCore.XmlDataTemp;

namespace CrawlerCore
{
    public class Abacus
    {
        public CrawlerHelper crawlerHelper { get; set; }
        public Abacus()
        {
            crawlerHelper = new CrawlerHelper();
        }
        private string getPostdata(SearchInputService myInputSearch)
        {
            StringBuilder postdata = new StringBuilder("");
            postdata.Append("from1=" + myInputSearch.DepartureCode);
            postdata.Append("&to1=" + myInputSearch.ArrivalCode);
            postdata.Append("&departureDate1=" + myInputSearch.DepartTime.ToString("yyyy-MM-dd") + "+09%3A01%3A00");
            int tripType = 1;
            if (myInputSearch.IsRoundTrip)
            {
                tripType = 2;
                postdata.Append("&from2=" + myInputSearch.ArrivalCode);
                postdata.Append("&to2=" + myInputSearch.DepartureCode);
                postdata.Append("&departureDate2=" + myInputSearch.ReturnTime.ToString("yyyy-MM-dd") + "+09%3A01%3A00");
            }
            postdata.Append("&tripType=" + tripType);
            postdata.Append("&adult=" + myInputSearch.Adults);
            postdata.Append("&child=" + myInputSearch.Children);
            postdata.Append("&infant=" + myInputSearch.Inf);
            postdata.Append("&student=0");
            postdata.Append("&seaman=0");
            postdata.Append("&seniorCitizen=0");
            postdata.Append("&labour=0");
            postdata.Append("&class=Y");
            postdata.Append("&flightType=2");
            postdata.Append("&prefAirline=");
            return postdata.ToString();
        }
        private string getPostdata2()
        {
            StringBuilder postdata = new StringBuilder("");
            postdata.Append("action_type=SEARCH");
            postdata.Append("&page=1");
            postdata.Append("&pagesize=50");
            return postdata.ToString();
        }
        public RootForeign CreateXmlDocument(SearchInputService input)
        {
            try
            {
                string adress = "https://abacuswebstart.abacus.com.sg/thong-minh/flight-search-process.aspx";

                CookieCollection c = crawlerHelper.getCookieCollection(adress, "POST", getPostdata(input));
                adress = "https://abacuswebstart.abacus.com.sg/thong-minh/ajax-flight.aspx";
                HtmlDocument d = crawlerHelper.getDocument(adress, "POST", getPostdata2(), c);
                d.DocumentNode.InnerHtml = d.DocumentNode.InnerHtml.Replace("<![CDATA[", " ");
                //tao doi tuong
                RootForeign rootf = new RootForeign();
                rootf.Departure = input.DepartureCode;
                rootf.Arrival = input.ArrivalCode;
                rootf.Flights = new List<FlightForeign>();
                HtmlNodeCollection nodeColection = d.DocumentNode.SelectNodes("//div[@class='wsFlightResult wsFlightResultBorder']");
                int i = 0;
                foreach (HtmlNode node in nodeColection)
                {
                    try
                    {
                        FlightForeign flight = new FlightForeign();
                        flight.Id = i;
                        i++;
                        flight.outBoundForeign = new OutInBoundForeign();
                        flight.inBoundForeign = new OutInBoundForeign();
                        flight.Source = AirLineName.abacus;
                        HtmlNode nodeFlight = node.SelectSingleNode("div/div[2]");
                        HtmlNode nodeDepart = nodeFlight.SelectSingleNode("div[1]");
                        flight.outBoundForeign.Segments = getSegments(input.DepartTime, nodeDepart, flight.outBoundForeign);
                        if (input.IsRoundTrip)
                        {
                            HtmlNode nodeReturn = nodeFlight.SelectSingleNode("div[3]");
                            flight.inBoundForeign.Segments = getSegments(input.ReturnTime, nodeReturn, flight.inBoundForeign);
                        }

                        //lay gia tong
                        HtmlNode nodePrice = node.SelectSingleNode("div/div[1]/div[3]");
                        flight.Price = decimal.Parse(nodePrice.InnerText) * MoneyRate.MONEY_RATE;

                        //lay gia chi tiet
                        HtmlNode nodePriceDetail = node.SelectSingleNode("div/div[1]/div[5]/table");
                        getPriceDetail(input, nodePriceDetail, flight);
                        rootf.Flights.Add(flight);
                    }
                    catch { }
                }
                ////ghi ra file xml
                //XmlSerializer serializer = new XmlSerializer(typeof(RootForeign));
                //TextWriter writer1 = new StreamWriter(folderPath + "Abacus_"+input.SessionId+".xml");
                //serializer.Serialize(writer1, rootf);
                //writer1.Close();
                return rootf;
            }
            catch
            {
                return null;
            }
        }
        //lay gia chi tiet cua nguoi lon,tre em,tre so sinh va gan vao bien flight
        private void getPriceDetail(SearchInputService input, HtmlNode nodePrice, FlightForeign flight)
        {
            int indexPrice = 1;
            if (input.Adults > 0)
            {
                HtmlNode nodeAdult = nodePrice.SelectSingleNode("tr[" + indexPrice + "]/td[2]");
                flight.PriceAdult = decimal.Parse(nodeAdult.InnerText) * MoneyRate.MONEY_RATE;
                indexPrice++;
            }
            if (input.Children > 0)
            {
                HtmlNode nodeChildren = nodePrice.SelectSingleNode("tr[" + indexPrice + "]/td[2]");
                flight.PriceChild = decimal.Parse(nodeChildren.InnerText) * MoneyRate.MONEY_RATE;
                indexPrice++;
            }
            if (input.Inf > 0)
            {
                HtmlNode nodeChildren = nodePrice.SelectSingleNode("tr[" + indexPrice + "]/td[2]");
                flight.PriceInfant = decimal.Parse(nodeChildren.InnerText) * MoneyRate.MONEY_RATE;
            }
            HtmlNode nodeTaxPrice = nodePrice.SelectSingleNode("tr[last()-1]/td[2]");
            flight.TaxPrice = decimal.Parse(nodeTaxPrice.InnerText) * MoneyRate.MONEY_RATE;
        }
        private List<SegmentForeign> getSegments(DateTime date, HtmlNode node, OutInBoundForeign outInBound)
        {
            if (node == null)
            {
                return null;
            }
            List<SegmentForeign> segments = new List<SegmentForeign>();
            SegmentForeign s = new SegmentForeign();
            HtmlNodeCollection nodeAirLines = node.SelectNodes("div[1]/div");
            if(nodeAirLines==null||nodeAirLines.Count==0)
                nodeAirLines = node.SelectNodes("div[1]");
            List<string> AirLines = new List<string>();
            foreach (HtmlNode node1 in nodeAirLines)
            {
                string t = node1.SelectSingleNode("img").Attributes["alt"].Value;
                AirLines.Add(t);
            }
            var note2 = node.SelectSingleNode("div[2]/div[4]");            
            List<string> listFlightNo = getListFlightNo(note2.InnerText.Replace("\r\n", ""));
            HtmlNode nodeTemp = node.SelectSingleNode("div[2]/div[6]");
            List<HtmlNode> collectionSegments = nodeTemp.SelectNodes("div").Where(i => i.SelectNodes("b") != null).ToList();
            int indexAirLine = 0, indexFlyNo = 0;
            foreach (HtmlNode node11 in collectionSegments)
            {
                if (node11.InnerText.StartsWith("Layover: "))
                {
                    s.LayOver = node11.InnerText.Replace("Layover: ", "").Trim();
                    segments.Add(s);
                }
                else if (node11.InnerText.StartsWith("Total trip time: "))
                {
                    segments.Add(s);
                    outInBound.TotalTime = node11.InnerText.Replace("Total trip time: ", "").Trim();
                }
                else
                {
                    s = new SegmentForeign();
                    string t1 = node11.SelectSingleNode("b").InnerText;
                    int k = t1.IndexOf(" to ");
                    s.Departure = t1.Substring(0, k).Trim();
                    s.Arrive = t1.Substring(k + 4).Trim();
                    node11.RemoveChild(node11.SelectSingleNode("b"));
                    string detail = node11.InnerHtml.Replace("\r\n", " ").Replace("<br>", ",");
                    detail = detail.Replace("Depart", "");
                    detail = detail.Replace("Arrive", ",");
                    detail = detail.Replace("Duration:", "");
                    string[] details = detail.Split(',');
                    s.Class = details[1].Trim();
                    s.FlightNo = listFlightNo[indexFlyNo];
                    indexFlyNo++;
                    string layOver = "";
                    DateTime newDepartTime = date;
                    if (segments.Count > 0)
                    {
                        if (segments.Last().LayOver.Length > 6)
                        {
                            layOver = segments.Last().LayOver.Substring(segments.Last().LayOver.Length - 7);
                        }
                        newDepartTime = segments.Last().ArriveTime;
                    }
                    s.DepartureTime = DateTimeHelper.getDateAbacusDepartTime(newDepartTime, details[3], layOver);
                    s.Duration = details[5].Trim();
                    //lay ngay den
                    s.ArriveTime = DateTimeHelper.getDateAbacusArriveTime(s.DepartureTime, details[4].Trim());

                    s.AirLine = AirLines[indexAirLine];
                    indexAirLine++;
                    if (indexAirLine >= AirLines.Count)
                    {
                        indexAirLine = AirLines.Count - 1;
                    }
                }

            }
            return segments;
        }

        private List<string> getListFlightNo(string p)
        {
            List<string> l = new List<string>();
            int end = -1;
            do
            {
                int flyNo = 0, tempNo = 0;
                end = p.IndexOf(" operated ");
                if (end == -1)
                {
                    break;
                }
                int start = end - 1;
                while ((p.ElementAt(start) == ' ' && flyNo == 0) || int.TryParse(p.Substring(start, end - start + 1), out tempNo))
                {
                    flyNo = tempNo;
                    start--;
                }
                l.Add(flyNo.ToString());
                p = p.Substring(end + 5);
            } while (true);
            return l;
        }
    }
}